package com.jack.lib.core.ext

import android.annotation.SuppressLint
import android.content.Context
import android.content.res.XmlResourceParser
import android.graphics.Rect
import android.view.*
import androidx.coordinatorlayout.widget.ViewGroupUtils
import androidx.core.view.get
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException
import java.io.IOException

/**
 * author : jack(黄冲)
 * e-mail : 907755845@qq.com
 * create : 2020/9/10
 * desc   :
 */

fun View.visible() {
    this.visibility = View.VISIBLE
}
fun View.invisible(invisible: Boolean = true) {
    this.visibility = if (invisible ) View.INVISIBLE else View.VISIBLE
}
fun View.gone(gone: Boolean = true) {
    this.visibility = if (gone ) View.GONE else View.VISIBLE
}

fun ViewPager2.setCachePool(offscreenPageLimit: Int, maxCacheCount: Int){
    this.offscreenPageLimit = offscreenPageLimit
    (this.getChildAt(0) as RecyclerView).setRecycledViewPool(RecyclerView.RecycledViewPool().apply { setMaxRecycledViews(0, maxCacheCount) })
    (this.getChildAt(0) as RecyclerView).setItemViewCacheSize(maxCacheCount)
}



fun View.dispatchSelected(selected: Boolean) {
    dispatchSelected(selfSet = true, recursive = true, selected = selected)
}

fun View.dispatchOnClickListener(listener: View.OnClickListener){
    dispatchOnClickListener(selfSet = false, recursive = false, listener = listener)
}

fun View.dispatchSelected(selfSet: Boolean = false, recursive: Boolean = false, selected: Boolean) {
    if (selfSet){
        isSelected = selected
    }
    if (this is ViewGroup){
        for (i in 0 until this.childCount){
            if (recursive){
                this[i].dispatchSelected(true, recursive, selected)
            }else{
                this[i].isSelected = selected
            }
        }
    }
}


fun View.dispatchOnClickListener(selfSet: Boolean = false, recursive: Boolean = false, listener: View.OnClickListener){
    if (selfSet){
        setOnClickListener(listener)
    }
    setOnClickListener(listener)
    if (this is ViewGroup){
        for (i in 0 until this.childCount){
            if (recursive){
                this[i].dispatchOnClickListener(true, recursive, listener)
            }else{
                this[i].setOnClickListener(listener)
            }
        }
    }
}

fun View.indexOfSelect(): Int {
    if (this is ViewGroup) {
        for (i in 0 until childCount) {
            if (getChildAt(i).isSelected) {
                return i
            }
        }
    }
    return -1
}


fun View.locationOnScreenRect(): Rect {
    val location = intArrayOf(0, 0)
    this.getLocationOnScreen(location)
    return Rect(location[0], location[1], location[0] + measuredWidth, location[1] + measuredHeight)
}

fun View.pointInView(x: Float, y: Float) = locationOnScreenRect().contains(x.toInt(), y.toInt())



    @SuppressLint("RestrictedApi")
fun View.expand(dx: Int, dy: Int) {
    // 将刚才定义代理类放到方法内部，调用方不需要了解这些细节
    class MultiTouchDelegate(bound: Rect? = null, delegateView: View) :
        TouchDelegate(bound, delegateView) {
        val delegateViewMap = mutableMapOf<View, Rect>()
        private var delegateView: View? = null

        override fun onTouchEvent(event: MotionEvent): Boolean {
            val x = event.x.toInt()
            val y = event.y.toInt()
            var handled = false
            when (event.actionMasked) {
                MotionEvent.ACTION_DOWN -> {
                    delegateView = findDelegateViewUnder(x, y)
                }
                MotionEvent.ACTION_CANCEL -> {
                    delegateView = null
                }
            }
            delegateView?.let {
                event.setLocation(it.width / 2f, it.height / 2f)
                handled = it.dispatchTouchEvent(event)
            }
            return handled
        }

        private fun findDelegateViewUnder(x: Int, y: Int): View? {
            delegateViewMap.forEach { entry -> if (entry.value.contains(x, y)) return entry.key }
            return null
        }
    }

    // 获取当前控件的父控件
    val parentView = parent as? ViewGroup
    // 若父控件不是 ViewGroup, 则直接返回
    parentView ?: return

    // 若父控件未设置触摸代理，则构建 MultiTouchDelegate 并设置给它
    if (parentView.touchDelegate == null) parentView.touchDelegate =
        MultiTouchDelegate(delegateView = this)
    post {
        val rect = Rect()
        // 获取子控件在父控件中的区域
        ViewGroupUtils.getDescendantRect(parentView, this, rect)
        // 将响应区域扩大
        rect.inset(-dx, -dy)
        // 将子控件作为代理控件添加到 MultiTouchDelegate 中
        (parentView.touchDelegate as? MultiTouchDelegate)?.delegateViewMap?.put(this, rect)
    }
}

fun Context.inflate(layoutId: Int): View {

    val view = View.inflate(this, layoutId, null)
    val parser: XmlResourceParser = resources.getLayout(layoutId)
    var type: Int
    try {
        while (parser.next().also { type = it } != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT);
        if (type != XmlPullParser.START_TAG) {
            throw InflateException(parser.positionDescription + ": 找不到开始标签!")
        }
    } catch (e: XmlPullParserException) {
        val ie = InflateException(e.message, e)
        ie.stackTrace = arrayOfNulls(0)
        throw ie
    } catch (e: IOException) {
        val ie = InflateException(e.message, e)
        ie.stackTrace = arrayOfNulls(0)
        throw ie
    }

    val params: ViewGroup.MarginLayoutParams = if (view is ViewGroup) {
        view.generateLayoutParams(parser).apply { view.layoutParams = this } as ViewGroup.MarginLayoutParams
    }else {
        ViewGroup.MarginLayoutParams(this, parser).apply { view.layoutParams = this }
    }

    val widthSpec = View.MeasureSpec.makeMeasureSpec(params.width, View.MeasureSpec.EXACTLY)
    val heightSpec = View.MeasureSpec.makeMeasureSpec(params.height, View.MeasureSpec.EXACTLY)
    view.measure(widthSpec, heightSpec)

    return view
}

